<template>
  <div v-if="type == 'tag'" class="tag-label gap-1">
    <template v-for="tag in options" :key="tag.id">
      <el-tag v-if="selectedValue == tag.code" :size="size">
        {{ tag.name }}
      </el-tag>
    </template>
  </div>
  <el-radio-group
    v-else-if="type == 'radio'"
    v-model="selectedValue"
    @change="handleChange"
  >
    <el-radio v-for="option in options" :key="option.id" :value="option.code">{{
      option.name
    }}</el-radio>
  </el-radio-group>
  <el-select
    v-else
    v-model="selectedValue"
    :placeholder="placeholder"
    :disabled="disabled"
    clearable
    @change="handleChange"
  >
    <el-option
      v-for="option in options"
      :key="option.id"
      :label="option.name"
      :value="option.code"
    />
  </el-select>
</template>

<script setup lang="ts">
import { getDictOptions } from "@/api/dict";
import { DictForm } from "@/api/dict/types";
import { useAppStore } from "@/store";

const props = defineProps({
  /**
   * 字典类型编码(eg: 性别-gender)
   * 如果传递了typeCode，会自动调用api获取。
   * 在table列表中不要传递， 否则每行都会调用api获取数据
   */
  typeCode: {
    type: String,
    required: false,
  },
  modelValue: {
    type: [String, Number],
  },
  placeholder: {
    type: String,
    default: "请选择",
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  type: {
    type: String,
    default: "select",
  },
  data: {
    type: Array,
    default: () => [],
  },
});

const emits = defineEmits(["update:modelValue", "change"]); // 父组件监听事件，同步子组件值的变化给父组件

const options: Ref<DictForm[]> = ref([]); // 字典下拉数据源

const selectedValue = ref<string | number | undefined>();

const appStore = useAppStore();

const size = computed(
  () => appStore.size as "default" | "small" | "large" | undefined
);

// 监听options或者modelValue发生变化时触发
watch([options, () => props.modelValue], ([newOptions, newModelValue]) => {
  if (newOptions.length === 0) return; // 下拉数据源加载未完成不回显
  if (newModelValue == undefined) {
    selectedValue.value = undefined;
    return;
  }
  if (typeof newOptions[0].code === "number") {
    selectedValue.value = Number(newModelValue);
  } else if (typeof newOptions[0].code === "string") {
    selectedValue.value = String(newModelValue);
  } else {
    selectedValue.value = newModelValue;
  }
});

watch(
  () => props.typeCode,
  (newVal) => {
    getOptions();
  }
);

function handleChange(val?: string | number | undefined) {
  emits("update:modelValue", val);
  emits("change", val);
}

onBeforeMount(() => {
  if (props.typeCode) {
    getOptions();
    return;
  }
  options.value = props.data;
});

const getOptions = () => {
  // 根据字典类型编码(typeCode)获取字典选项
  options.value = [];
  getDictOptions(props.typeCode).then((response) => {
    options.value = response.data;
  });
};
</script>

<style scoped lang="scss">
.tag-label {
  display: flex;
  justify-content: center;
}

:deep(.el-tag) {
  border-width: 0px;
}
</style>
